#include "aio_helper.h"
#include "../global/head.h"
#include "../xos/head.h"
#include "../buf/head.h"
#include "aio_callback_thread.h"
#include "../msg/head.h"
#include "aio_thread.h"
#include "aio_impl.h"
#include "aio_key.h"
#include "aio_tcp.h"
#include "aio_udp.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    aio_helper::aio_helper( aio_impl * pAioImpl ) : m_pAioImpl( pAioImpl )
    {
    }

    aio_helper::~aio_helper()
    {
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // epoll event
    // 
    int aio_helper::epoll_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        i_handle * lpHand = lpKey->m_pHandle;
        i_xos::enumXosObj eType = lpHand->obj_type();

        switch( eType )
        {
        case i_xos::XOS_OBJ_TCP:
            {
                tcp_proc( lpKey, nFilter, nFlags, nData );
            }
            break;
        case i_xos::XOS_OBJ_UDP:
            {
                udp_proc( lpKey, nFilter, nFlags, nData );
            }
            break;
        default:
            {
            }
            break;
        }

        return nRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int aio_helper::tcp_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        aio_tcp tool( m_pAioImpl );

        switch( lpKey->m_enumHandleType )
        {
        case aio_key::H_TYPE_TCP_CONN:
            {
                lpKey->m_nCanWriteSize = nData;
                lpKey->m_bCanWrite = true;
                tool.tcp_recv_connect( lpKey, nFilter );
            }
            break;
        case aio_key::H_TYPE_TCP_SERVER:
            {
                tool.tcp_accept( lpKey, nFilter );
            }
            break;
        case aio_key::H_TYPE_TCP_NORM:
            {
                if( nFlags &  EV_ERROR )
                {
                    tool.tcp_error( lpKey );
                }
                else
                {
                    if( EVFILT_WRITE == nFilter )
                    {
                        lpKey->m_nCanWriteSize = nData;
                        lpKey->m_bCanWrite = true;
                        tool.tcp_send( lpKey );
                    }
                    else if( EVFILT_READ == nFilter )
                    {
                        lpKey->m_nCanReadSize = nData;
                        tool.tcp_recv( lpKey );
                    }
                }
            }
            break;
        default:
            {
            }
            break;
        }

        return nRet;
    }

    int aio_helper::udp_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        aio_udp tool( m_pAioImpl );

        if( nFlags & EV_ERROR )
        {
            tool.udp_error( lpKey );
        }
        else
        {
            if( EVFILT_WRITE == nFilter )
            {
                lpKey->m_nCanWriteSize = nData;
                lpKey->m_bCanWrite = true;
                tool.udp_send( lpKey );
            }
            else if( EVFILT_READ == nFilter )
            {
                lpKey->m_nCanReadSize = nData;
                tool.udp_recv( lpKey );
            }
        }

        return nRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // process user request 
    // 
    int aio_helper::user_request()
    {
        using namespace std;
        int nRet = 0;

        msg_impl::LIST & buf_list = m_pAioImpl->m_request_list;
        bool bFinished = false;

        while( !bFinished  )
        {
            msg_impl * p = 0;

            buf_list.lock();
            p = buf_list.front();
            if( p )
            {
                buf_list.pop_front();
            }
            buf_list.unlock();

            if( p )
            {
                helper_proc( p );
                p = 0;
            }
            else
            {
                bFinished = true;
            }
        }

        return nRet;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::helper_proc( msg_impl * lpMsg )
    {
        using namespace std;
        int nRet = 0;

        i_aio::enumAioType eType = ( i_aio::enumAioType )lpMsg->m_nData[0];

        switch( eType )
        {
            // 
            // tcp
            // 
        case i_aio::AIO_TCP_INIT_SERVER:
        case i_aio::AIO_TCP_CONNECT:
        case i_aio::AIO_TCP_ACCPET:
        case i_aio::AIO_TCP_RECV:
        case i_aio::AIO_TCP_SEND:
        case i_aio::AIO_TCP_CLOSE_HANDLE:
            {
                nRet = user_tcp( lpMsg );
                lpMsg = 0;
            }
            break;

            // 
            // udp
            // 
        case i_aio::AIO_UDP_INIT:
        case i_aio::AIO_UDP_RECV:
        case i_aio::AIO_UDP_SEND:
        case i_aio::AIO_UDP_CLOSE_HANDLE:
            {
                nRet = user_udp( lpMsg );
                lpMsg = 0;
            }
            break;

        default:
            {
                cout << lpMsg << " is a unknown request type" << endl;
            }
            break;
        }

        if( lpMsg )
        {
            lpMsg->release();
            lpMsg = 0;
        }

        return nRet;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_tcp( msg_impl * lpMsg )
    {
        using namespace std;
        int nRet = 0;

        i_aio::enumAioType eType = ( i_aio::enumAioType )lpMsg->m_nData[0];
        aio_tcp tcp( m_pAioImpl );

        switch( eType )
        {
            // 
            // tcp
            // 
        case i_aio::AIO_TCP_INIT_SERVER:
            {
                nRet = tcp.user_init_server( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_TCP_CONNECT:
            {
                nRet = tcp.user_connect( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_TCP_ACCPET:
            {
                nRet = tcp.user_accept( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_TCP_RECV:
            {
                nRet = tcp.user_recv( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_TCP_SEND:
            {
                nRet = tcp.user_send( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_TCP_CLOSE_HANDLE:
            {
                nRet = tcp.close_handle( lpMsg );
                lpMsg = 0;
            }
            break;

            // 
            // default
            // 
        default:
            {
                cout << lpMsg << " is a unknown request type" << endl;
            }
            break;
        }

        if( lpMsg )
        {
            lpMsg->release();
            lpMsg = 0;
        }

        return nRet;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_udp( msg_impl * lpMsg )
    {
        using namespace std;
        int nRet = 0;

        i_aio::enumAioType eType = ( i_aio::enumAioType )lpMsg->m_nData[0];
        aio_udp udp( m_pAioImpl );

        switch( eType )
        {
            // 
            // udp
            // 
        case i_aio::AIO_UDP_INIT:
            {
                nRet = udp.user_init_server( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_UDP_RECV:
            {
                nRet = udp.user_recv( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_UDP_SEND:
            {
                nRet = udp.user_send( lpMsg );
                lpMsg = 0;
            }
            break;
        case i_aio::AIO_UDP_CLOSE_HANDLE:
            {
                nRet = udp.close_handle( lpMsg );
                lpMsg = 0;
            }
            break;

            // 
            // 
            // 
        default:
            {
                cout << lpMsg << " is a unknown request type" << endl;
            }
            break;
        }

        if( lpMsg )
        {
            lpMsg->release();
            lpMsg = 0;
        }

        return nRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 0 : not quit; not 0, quit 
    // 
    int aio_helper::timeout()
    {
        int nRet = 0;
        return nRet;
    }
    
} // xos
